package enaming

//nacos 服务发现

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"git.edaijia-inc.cn/edaijia/ego/elogger"
	"git.edaijia-inc.cn/edaijia/ego/etools"

	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"
)

type ENamingConfig struct {
	NacosAddr   string `ini:"nacosaddr"`
	NacosPort   uint64 `ini:"nacosport"`
	Namespace   string `ini:"namespace"`
	ClusterName string `ini:"clustername"`
	GroupName   string `ini:"groupname"`
}

type ENaming struct {
	Client naming_client.INamingClient
	Conf   *ENamingConfig
}

var gENaming *ENaming

func InitENaming(conf *ENamingConfig) {
	//todo check config
	var err error

	serverConfig := []constant.ServerConfig{
		{
			IpAddr: conf.NacosAddr,
			Port:   conf.NacosPort,
		},
	}

	clientConfig := constant.ClientConfig{
		NamespaceId:         conf.Namespace,
		TimeoutMs:           5000,
		ListenInterval:      10000,
		NotLoadCacheAtStart: true,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		RotateTime:          "1h",
		MaxAge:              3,
		LogLevel:            "info",
	}

	client, err := clients.CreateNamingClient(map[string]interface{}{
		"serverConfigs": serverConfig,
		"clientConfig":  clientConfig,
	})

	if err != nil {
		panic(err)
	}

	gENaming = &ENaming{client, conf}

}

func Register(name string, httpaddr string) error {
	var err error

	if gENaming == nil {
		return errors.New("failed to get service addr, please init ENaming firstly")
	}

	ipPort := strings.Split(httpaddr, ":")
	if len(ipPort) > 2 {
	}

	var port uint64
	var ip string
	if len(ipPort) == 1 {
		port = 80
	} else {
		port, err = strconv.ParseUint(ipPort[1], 10, 64)
		if err != nil {
			elogger.Error("enaming service port error", err)
			return err
		}
	}
	if len(ipPort[0]) == 0 || ipPort[0] == "0.0.0.0" {
		eth0Ips := etools.GetInterfaceIp("eth0")
		if len(eth0Ips) == 0 {
			elogger.Error("enaming service ip or host error")
			return errors.New("enaming service ip or host error")
		}

		ip = eth0Ips[0]
	} else {
		ip = ipPort[0]
	}

	param := vo.RegisterInstanceParam{
		Ip:          ip,
		Port:        port,
		ServiceName: name,
		Weight:      10,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		ClusterName: gENaming.Conf.ClusterName,
		GroupName:   gENaming.Conf.GroupName,
	}

	_, err = gENaming.Client.RegisterInstance(param)
	if err != nil {
		elogger.Error("enaming register instance error", err)
		return err
	}

	elogger.Info("success to register service instance to nacos ", name+"->"+httpaddr)
	return nil
}

func GetClient(serviceName string, groupName string, clusterName string) (string, error) {
	if gENaming == nil {
		return "", errors.New("failed to get service addr, please init ENaming firstly")
	}

	if groupName == "" {
		groupName = gENaming.Conf.GroupName
	}
	if clusterName == "" {
		clusterName = gENaming.Conf.ClusterName
	}
	instance, err := gENaming.Client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
		ServiceName: serviceName,
		GroupName:   groupName,
		Clusters:    []string{clusterName},
	})

	if err != nil {
		elogger.Error("enaming get client instance error, ", serviceName, ", ", err)
		return "", err
	}

	return fmt.Sprintf("%s:%d", instance.Ip, instance.Port), nil
}

func GetAllClient(serviceName string, groupName string, clusterName string) []string {
	var ips []string
	if gENaming == nil {
		return ips
	}

	if groupName == "" {
		groupName = gENaming.Conf.GroupName
	}
	if clusterName == "" {
		clusterName = gENaming.Conf.ClusterName
	}
	instance, err := gENaming.Client.SelectInstances(vo.SelectInstancesParam{
		ServiceName: serviceName,
		GroupName:   groupName,
		Clusters:    []string{clusterName},
		HealthyOnly: true,
	})

	if err != nil {
		elogger.Error("enaming GetAllClient instance error, ", serviceName, ", ", err)
		return ips
	}
	for _, m := range instance {
		ip := fmt.Sprintf("%s:%d", m.Ip, m.Port)
		ips = append(ips, ip)
	}
	return ips
}
